package com.qdsg.modulesihealsdk.detectStrategy.strategy.bpStrategy;

import static com.invs.UsbBase.ACTION_USB_PERMISSION;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.Message;

import androidx.annotation.NonNull;

import com.example.moduleutils.LogUtil;
import com.google.gson.Gson;
import com.printsdk.usbsdk.UsbDriver;
import com.qdsg.modulesihealsdk.detectStrategy.control.StrategyCallback;
import com.qdsg.modulesihealsdk.entity.BpResultEntity;
import com.example.moduleutils.CachedThreadPoolSingleton;
import com.qdsg.modulesihealsdk.utils.SihealSdkConstant;
import com.qdsg.modulesihealsdk.detectStrategy.control.DetectBusiness;
import com.siheal.device.reader.measure.BloodPressureReader;
import com.siheal.device.reader.singlechip.DataChannelReader;
import com.siheal.entitys.device.DeviceOp;
import com.siheal.entitys.measure.BloodPressureEntity;
import com.siheal.exception.BasicException;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @Description
 * @Author WuJianFeng
 * @Date 2022/11/21 11:54
 */
public class BpStrategy implements DetectBusiness {

    private DataChannelReader dataChannelReader;
    private BloodPressureReader bloodPressureReader;


    //血压计是否正在测量中
    private boolean bloodPressureIsReading = false;

    //是否可以启动测量
    private boolean bloodPressureSwitch = false;

    //上次血压测量出结果时间戳
    private long lastBloodPressureTime = 0L;
    /**
     *
     * haveGetReceive：是否已出值标志，防止出值后还去调用process方法
     */
    private Boolean haveGetReceive = false;

    private UsbManager usbManager;
    private UsbDriver mUsbDriver;

    private UsbDeviceConnection usbDeviceConnection;
    private byte[] reciveByte = new byte[256];
    private Timer readPressureSwitchTimer = null;
    private Context context;
    private BpCallback bpCallback;
    private int progress = 0;

    @Override
    public void dealDetect(Context context, StrategyCallback strategyCallback) {
        this.context = context;
        haveGetReceive = false;
        progress = 0;
        if (strategyCallback instanceof BpCallback){
            this.bpCallback = (BpCallback)strategyCallback;
            bpCallback.detectProgress(0);
            detectBloodPressure();
        }
    }

    final Handler handler = new Handler(){

        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what == SihealSdkConstant.MSG_BP){
                if (!haveGetReceive){
                    if (bpCallback != null){
                        bpCallback.occurError(new BasicException());
                    }
                }
            }
        }
    };




    @Override
    public void stopThread() {
        handler.removeMessages(SihealSdkConstant.MSG_BP);
        try {

            if (bloodPressureReader != null){
                bloodPressureReader.stopRead();
                bloodPressureReader = null;
            }
            if (usbManager != null){
                usbManager = null;
            }
            if (mUsbDriver != null){
                mUsbDriver.closeUsbDevice();
                mUsbDriver = null;
            }
            if (usbDeviceConnection != null){
                usbDeviceConnection.close();
                usbDeviceConnection = null;
            }

            if (readPressureSwitchTimer != null){
                readPressureSwitchTimer.cancel();
                readPressureSwitchTimer = null;
            }

        }catch (Exception e){

        }

        haveGetReceive = false;
        bloodPressureIsReading = false;
        bloodPressureSwitch = false;
        if (bpCallback != null){
            bpCallback = null;
        }
    }

    private void detectBloodPressure(){

        //读取血压计触碰开关信号
        readPressureSwitch();


    }


    //读取血压计触碰开关信号
    private void readPressureSwitch(){
        usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        if (usbManager != null){
            HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
            Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
            while (deviceIterator.hasNext()) {
                UsbDevice usbDevice = deviceIterator.next();
                if (usbDevice.getProductId() == 29987 && usbDevice.getVendorId() == 6790) {
                    usbDevice.getProductName();
                    mUsbDriver = new UsbDriver(usbManager, context);
                    if (mUsbDriver != null){
                        PendingIntent permissionIntent1 = PendingIntent.getBroadcast(context,//
                                0, new Intent(ACTION_USB_PERMISSION), 0);
                        mUsbDriver.setPermissionIntent(permissionIntent1);
                        // Broadcast listen for new devices
                        IntentFilter filter = new IntentFilter();
                        filter.addAction(ACTION_USB_PERMISSION);
                        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
                        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
                        usbManager.requestPermission(usbDevice, permissionIntent1); // 该代码执行后，系统弹出一个对话框/等待权限
                        //开关按下开始读取数值
                        mUsbDriver.openUsbDevice(usbDevice);
                        readUsbInfo(usbManager, usbDevice);
                    }
                }
            }
        }
    }



    int releaseTimes = 0;
    //血压，开关按下开始读取数值
    private void readUsbInfo(final UsbManager usbManager , final UsbDevice device){
        releaseTimes = 0;
        final UsbInterface usbInterface = device.getInterface(0);
        final UsbEndpoint epBulkIn = usbInterface.getEndpoint(0);// 读信息
        usbDeviceConnection = null;
        if (usbInterface != null) {
            readPressureSwitchTimer = new Timer();
            readPressureSwitchTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    // open前判断连接权限
                    if (usbManager != null && usbManager.hasPermission(device)) {
                        // 打开USB设备，以便向此USB设备发送和接受数据，返回一个关于此USB设备的连接
                        usbDeviceConnection = usbManager.openDevice(device);
                    }
                    if (usbDeviceConnection != null && usbDeviceConnection.claimInterface(usbInterface, true)) {
                        if (usbDeviceConnection != null) {
                            // android设备已经连接硬件设备
                            // 接收发送成功信息(相当于读取设备数据)
                            usbDeviceConnection.controlTransfer(0x40, 0x03, 0x4138, 0, null, 0, 1000);
                            try {
                                Thread.sleep(400);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            //读取开关信号，a==1表明开关被触碰，按下弹起均为1
                            if (usbDeviceConnection != null){
                                int a = usbDeviceConnection.bulkTransfer(epBulkIn, reciveByte, reciveByte.length, 1000);
                                Long currentTime = System.currentTimeMillis();
                                //上次测量出结果时间与当前时间的间隔
                                int diff = (int) ((currentTime - lastBloodPressureTime)/1000);

                                //释放开关信号
                                if (releaseTimes < 2){
                                    releaseTimes ++;
                                    return;
                                }

                                if(a > 0 &&  diff > 15 && bloodPressureIsReading != true){
                                    if (a == 1){
                                        bloodPressureSwitch = !bloodPressureSwitch;
                                    }
                                    if(!bloodPressureSwitch){
                                        return;
                                    }
                                    if (readPressureSwitchTimer != null){
                                        readPressureSwitchTimer.cancel();
                                    }
                                    startDetect();
                                    //sendUIMessageDelayed(UI_MSG_START_MEASURE,0);
                                }
                            }
                        }
                    }
                }
            }, 0, 300);
        }
    }

    private void startDetect(){

        dataChannelReader = (new DataChannelReader(SihealSdkConstant.channelID_BP, context){
            // 数据通道切换成功，开始调用血压方法
            @Override
            public void resultReceived(DeviceOp result) {
                bloodPressureReader = (new BloodPressureReader(context) {
                    //血压数据获取成功，开始做后续数据处理，当前操作将结果数据回显至H5页面
                    //获取一次结果(最终结果)，在此方法中接收检测结果
                    @Override
                    public void resultReceived(BloodPressureEntity result) {
                        String data = new Gson().toJson(result);
                        LogUtil.logAndWrite("__bp-resultReceived",data);

                        //得到数据
                        progress = 0;
                        bloodPressureIsReading = false;
                        if (bpCallback != null && !haveGetReceive){
                            bpCallback.detectProgress(100);
                            haveGetReceive = true;
                            bpCallback.resultReceived(new BpResultEntity(result));
                        }

                    }

                    //无需处理
                    @Override
                    public void process(BloodPressureEntity middleResult) {
                        String data = new Gson().toJson(result);
                        LogUtil.logAndWrite("__bp-process",data);

                        int deviceStatu = middleResult.getMidStatu();
                        //血压计正在测量中
                                  /*  public static final int MEASURE_STATUS_CMD_SUCCESS = 1200;//指令正确（使用控制指令控制设备应收到此回传值）
                                    public static final int MEASURE_STATUS_CMD_DEVICE_ON = 1201;//设备开机
                                    public static final int  MEASURE_STATUS_CMD_DEVICE_READY = 1202;//设备准备完成
                                    public static final int MEASURE_STATUS_CMD_DEVICE_OFF = 1203;//设备关机
                                    public static final int MEASURE_STATUS_CMD_DEVICE_START = 1204;//开始测量
                                    public static final int MEASURE_STATUS_CMD_DEVICE_MEASUREING = 1205;//测量中
                                    public static final int MEASURE_STATUS_CMD_DEVICE_FINISH = 1206;//测量停止或测量完成*/
                        if (deviceStatu > 1200){
                            bloodPressureIsReading = true;
                            if (deviceStatu == 1205){
                                if (!haveGetReceive && bpCallback != null){
                                    fakeProgress();
                                    bpCallback.process(new BpResultEntity(middleResult));
                                }
                            }else if (deviceStatu == 1206){
                                bloodPressureIsReading = false;
                                //测量结束后一段时间内没拿到结果则判为测量失败
                                Message message = Message.obtain();
                                message.what = SihealSdkConstant.MSG_BP;
                                handler.sendMessageDelayed(message,5000);
//                                stopThread();
                            }

                        }
                    }

                    //调用过程中出现的异常
                    @Override
                    public void occurError(BasicException e) {
                                   /*
                                    int MEASURE_OUT_RANGE_EXCEPTION = 1001;//测量失败建议重测 temperature <= 32 || temperature >= 42.9
                                    int MEASURE_TIME_OUT = 1005;//测量超时
                                   */
                        bloodPressureIsReading = false;
                        String data = new Gson().toJson(e);
                        LogUtil.logAndWrite("__bp-occurError",data);
                        if (bpCallback != null){
                            bpCallback.occurError(e);
                        }
                    }
                });
                if (bloodPressureReader != null){
                    bloodPressureReader.start();
                }
            }
            //数据通道切换process方法，实现了父类抽象方法，在此无实义
            @Override
            public void process(DeviceOp middleResult) {}
            //数据通道切换异常处理方法
            @Override
            public void occurError(BasicException exception) {
                          /*  int ERROR_IO = 1;     //打开设备" + device.getDeviceID() + "数据通道异常
                            int ERROR_WRITE_DATA = 2;//设备" + device.getDeviceID() + "写入数据发生异常
                            int ERROR_USB_NOT_FOUND = 2001;//没有找到指定地址下(" + device.getPath() + ")设备
                            int ERROR_USB_NOT_SUPPORT = 2002;//本系统不支持USB模块
                            int ERROR_USB_UNKONW_TYPE = 2003;//未知的USB设备类型
                            int ERROR_USB_REQUEST_PERMISSION = 2004;//请求usb权限失败
                             int MEASURE_PROBE_CONFIG_ERROR = 1008;//配置文件配置错误
                            int ERROR_USB_DEVICE_OPEN = 2005;//打开usb设备错误*/
                if (bpCallback != null){
                    bpCallback.occurError(exception);
                }
            }
        });
        if (dataChannelReader != null){
            dataChannelReader.start();
        }
    }

    private void fakeProgress(){
        CachedThreadPoolSingleton.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    if (bpCallback != null && bloodPressureIsReading){
                        if (progress < 90){
                            progress = progress + 4;
                            bpCallback.detectProgress(progress);
                            fakeProgress();
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }

}
